Annotations注解(Android)

API开发文档:https://developer.android.com/studio/write/annotations.html

注解

注解是一种元数据, 可以添加到java代码中. 类、方法、变量、参数、包都可以被注解,可用来将信息元数据与程序元素进行关联,注解对注解的代码没有直接影响.

注解库

如果你使用了com.android.support:appcompat-v7库不需要添加额外的依赖。
但是如果你没有使用这个库,也可以额外单独添加注解库。compile 'com.android.support:support-annotations:xx.xx.xx'。

注解的作用

便于生成文档。
用于编译时的检查。
用于简洁化代码。

一:标准 Annotation

Nullness注解

@Nullable
@NonNull

 /** Add support for inflating the <fragment> tag. **/
    @NonNull
    @Override
    public View onCreateView(String name, @NonNull Context context,
      @NonNull AttributeSet attrs) {
     
      }

资源类型的注解

public abstract void setTitle(@StringRes int resId) { … }

资源类型的注解,有以下几种:

@StringRes
@ColorRes
@AnimationRes
@DimensionRes
@DimensionPixelOffsetRes
@DimensionPixelSizeRes
@BooleanRes
@ColorStateListRes
@DrawableRes
@IntArrayRes
@IntegerRes
@LayoutRes
@MovieRes
@TextRes
@TextArrayRes
@StringArrayRes

Thread 注解

@MainThread

@UiThread

@WorkerThread

@BinderThread

@AnyThread

值约束注释

@IntRange

public void setAlpha(@IntRange(from=0,to=255) int alpha) { … }

@FloatRange

public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {...}

@Size
最大值 (such as @Size(min=2))
最小值(such as @Size(max=2))
限定值 (such as @Size(2))

int[] location = new int[3];
button.getLocationOnScreen(@Size(min=1) location);

Permission 权限注解

对于有些方法可能需要系统的一些权限,但是我们会忘了在Manifest中加入这些权限,导致程序报错。

例如:
单个权限:

@RequiresPermission(Manifest.permission.SET_WALLPAPER)
public abstract void setWallpaper(Bitmap bitmap) throws IOException;```

例如存储卡权限(多个权限)

@RequiresPermission(allOf = {
Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE})
public static final void copyFile(String dest, String source) { ...}

对于Intent权限限制,在需要权限的action中添加权限:

@RequiresPermission(android.Manifest.permission.BLUETOOTH)
public static final String ACTION_REQUEST_DISCOVERABLE =
"android.bluetooth.adapter.action.REQUEST_DISCOVERABLE";

对于ContentProviders 需要区分read和write权限,可以采用[@RequiresPermission.Read ](https://developer.android.com/reference/android/support/annotation/RequiresPermission.Read.html)或者 [@RequiresPermission.Write ](https://developer.android.com/reference/android/support/annotation/RequiresPermission.Write.html)

注解如下:

@RequiresPermission.Read(@RequiresPermission(READ_HISTORY_BOOKMARKS))
@RequiresPermission.Write(@RequiresPermission(WRITE_HISTORY_BOOKMARKS))
public static final Uri BOOKMARKS_URI = Uri.parse("content://browser/bookmarks");

直接添加权限:
 [startActivity(Intent)](https://developer.android.com/reference/android/app/Activity.html#startActivity(android.content.Intent))


public abstract void startActivity(@RequiresPermission Intent intent, @Nullable Bundle) {...}```

@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
@RequiresPermission(Manifest.permission.CALL_PHONE)
public static final String ACTION_CALL = "android.intent.action.CALL";

返回值注解

@CheckResult

 @CheckResult(suggest="#enforcePermission(String,int,int,String)")
public abstract int checkPermission(@NonNull String permission, int pid, int uid);

强制super注解

比如我们写一个基类:

public class Base {
    @CallSuper
    public void test(){
        Log.e("","");
    }
}```

##Typedef 类型注解
 [@IntDef](https://developer.android.com/reference/android/support/annotation/IntDef.html)
 [@StringDef](https://developer.android.com/reference/android/support/annotation/StringDef.html)

IntDef StringDef可以限制传入参数的内容,这在一些固定参数的方法中尤为重要

public abstract class ActionBar {
...
// Define the list of accepted constants and declare the NavigationMode annotation
@Retention(RetentionPolicy.SOURCE)
@IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
public @interface NavigationMode {}

// Declare the constants
public static final int NAVIGATION_MODE_STANDARD = 0;
public static final int NAVIGATION_MODE_LIST = 1;
public static final int NAVIGATION_MODE_TABS = 2;

// Decorate the target methods with the annotation
@NavigationMode
public abstract int getNavigationMode();

// Attach the annotation
public abstract void setNavigationMode(@NavigationMode int mode);

##@keep
 [@Keep](https://developer.android.com/reference/android/support/annotation/Keep.html)
 
一看到这个词肯定第一反应就是跟混淆相关的,没错,这个就是标识该方法被keep出来,当然你也可以在混淆文件中keep



#二:元注解

Override注解的源码

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}```

元注解就是用来定义注解的注解.其作用就是定义注解的作用范围, 使用在什么元素上等等, 下面来详细介绍.

元注解共有四种
  • @Documented –注解是否将包含在JavaDoc中
  • @Retention –什么时候使用该注解
  • @Target –注解用于什么地方
  • @Inherited – 是否允许子类继承该注解

@Retention

@Retention 保留的范围,默认值为CLASS. 可选值有三种
SOURCE, 只在源码中可用
CLASS, 在源码和字节码中可用
RUNTIME, 在源码,字节码,运行时均可用


  • RetentionPolicy.SOURCE – 在编译阶段丢弃。这些注解在编译结束之后就不再有任何意义,所以它们不会写入字节码。@Override, @SuppressWarnings都属于这类注解。
  • RetentionPolicy.CLASS – 在类加载的时候丢弃。在字节码文件的处理中有用。注解默认使用这种方式。
  • RetentionPolicy.RUNTIME – 始终不会丢弃,运行期也保留该注解,因此可以使用反射机制读取该注解的信息。我们自定义的注解通常使用这种方式。

@Target

@Target 可以用来修饰哪些程序元素,如 TYPE, METHOD, CONSTRUCTOR, FIELD, PARAMETER等,未标注则表示可修饰所有

  • 取值(ElementType)有:

1.CONSTRUCTOR:用于描述构造器
2.FIELD:用于描述域
3.LOCAL_VARIABLE:用于描述局部变量
4.METHOD:用于描述方法
5.PACKAGE:用于描述包
6.PARAMETER:用于描述参数
7.TYPE:用于描述类、接口(包括注解类型) 或enum声明


@Inherited

@Inherited 是否可以被继承,默认为false


@Documented

@Documented 是否会保存到 Javadoc 文档中


其中, @Retention是定义保留策略, 直接决定了我们用何种方式解析. SOUCE级别的注解是用来标记的, 比如Override, SuppressWarnings. 我们真正使用的类型是CLASS(编译时)和RUNTIME(运行时)

三:自定义注解

自定义 Annotation 表示自己根据需要定义的 Annotation,定义时需要用到上面的元 Annotation
这里是一种分类而已,也可以根据作用域分为源码时、编译时、运行时 Annotation

使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节。在定义注解时,不能继承其他的注解或接口。@interface用来声明一个注解,其中的每一个方法实际上是声明了一个配置参数。方法的名称就是参数的名称,返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)。可以通过default来声明参数的默认值。

定义注解格式:

public @interface 注解名 {定义体}

注解参数的可支持数据类型:

1.所有基本数据类型(int,float,boolean,byte,double,char,long,short)
2.String类型
3.Class类型
4.enum类型
5.Annotation类型
6.以上所有类型的数组


Annotation类型里面的参数该怎么设定:
  • 第一,只能用public或默认(default)这两个访问权修饰.例如,String value();这里把方法设为defaul默认类型;
  • 第二,参数成员只能用基本类型byte,short,char,int,long,float,double,boolean八种基本数据类型和 String,Enum,Class,annotations等数据类型,以及这一些类型的数组.例如,String value();这里的参数成员就为String;
  • 第三,如果只有一个参数成员,最好把参数名称设为"value",后加小括号.例:下面的例子FruitName注解就只有一个参数成员。
注意:
  • 注解可以设定初始值,使用default就可以实现。
  • 注解只有一个元素的时候,该元素名称必须是value,并且在使用该注解的时候可以省略”alue=”。

  • 注解的值必须是确定的,且不能使用null作为值。

  • 注解可能的类型:所有基本类型、String、Class、enum、Annotation、以上类型的数组形式。

  • 举个例子

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface TestAnnotation {
    String value();
    String[] value2() default "value2";
}```

元注解的的意义参考上面的讲解, 不再重复, 这里看注解值的写法:

类型 参数名() default 默认值;
其中默认值是可选的, 可以定义, 也可以不定义
* 自己写的例子:
自定义一个注解:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ ElementType.METHOD ,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {
String isAop() default "false";
}

通过反射机制获取:

public class TestProcess {

public static void process(String str) throws ClassNotFoundException {

    Class clazz = Class.forName(str);

    Annotation[] annotations = clazz.getAnnotations();

    for (Annotation annotation : annotations) {
        System.out.println(annotation.);
    }
}

}

测试使用:

@Test(isAop = "false")

public class UseTest {
public static void main(String[] args) {
try {
TestProcess.process("Test");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}




###参考链接:
>[公共技术点之 Java 注解 Annotation](http://a.codekk.com/detail/Android/Trinea/%E5%85%AC%E5%85%B1%E6%8A%80%E6%9C%AF%E7%82%B9%E4%B9%8B%20Java%20%E6%B3%A8%E8%A7%A3%20Annotation)
[[自定义注解定义和使用](http://blog.csdn.net/u012150370/article/details/47304435)](http://blog.csdn.net/u012150370/article/details/47304435)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,026评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,655评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,726评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,204评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,558评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,731评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,944评论 2 314
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,698评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,438评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,633评论 2 247
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,125评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,444评论 3 255
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,137评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,103评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,888评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,772评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,669评论 2 271

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,103评论 18 139
  • 什么是注解(Annotation):Annotation(注解)就是Java提供了一种元程序中的元素关联任何信息和...
    九尾喵的薛定谔阅读 3,077评论 0 2
  • 本文章涉及代码已放到github上annotation-study 1.Annotation为何而来 What:A...
    zlcook阅读 28,926评论 15 116
  • 整体Retrofit内容如下: 1、Retrofit解析1之前哨站——理解RESTful 2、Retrofit解析...
    隔壁老李头阅读 6,206评论 4 31
  • 今天看了kn,好多人在评论xl、k a。 看到评论里骂来骂去的,我突然不喜欢73了。每一个人都喜欢把自己的感情注入...
    殘彧阅读 188评论 0 0